//页面渲染和计算属性都用watcher
let uid = 0; //每次新创建一个watcher，必须有一个标识
import {pushTarget,popTarget} from "../observer/dep"
class Watcher {
    /**
     * @param {*} vm  组件的实例 
     * @param {*} expOrFn 用户传入的是一个表达式或者是一个函数 computed可以为函数，也可以为一个{get:function,set:function}对象
     * @param {*} cb  用户传入的回调函数，比如 vm.$watch(prop,cb)
     * @param {*} options 其他一些参数
     * @param {*} isRenderWatcher 是否是渲染watcher
     */
    constructor(vm,expOrFn,cb=()=>{},options={},isRenderWatcher){
        this.vm = vm
        this.expOrFn = expOrFn
        if(typeof this.expOrFn == 'function'){  //computed直接传入函数
            this.getter = expOrFn
        }else{ //传入对象
            this.getter = expOrFn.get;
            this.setter = expOrFn.set;
        }
        this.cb = cb
        this.options = options
        this.id = uid++;
        this.deps = [];
        this.depsId = new Set();
        this.get();
    }
    //执行get方法
    get(){
        //如果是组件，调用的是更新和渲染组件的函数
        //如果是computed,则返回的是一个属性
        pushTarget(this);
        this.getter()
        popTarget();
    }
    /**
     * @description 每一个watcher实例都提供一个update方法
     */
    update(){
        console.log()
        this.get(this.id)   //不能直接调用this.get() 否则每次调用都会更新，需要异步更新
    //    queueWatcher()
    }
    addDep(dep){
        const id = dep.id;
        
        if(!this.depsId.has(id)){  //同一个watcher不应该重复记录dep
            this.depsId.add(id);
            this.deps.push(dep); //watcher记录了dep
            dep.addSub(this); //就让watcher记住当前的dep
        }
    }
}
export default Watcher